package com.rlax.framework.plugin.reids.shiro;

import com.jfinal.plugin.redis.Redis;
import com.rlax.framework.common.CacheKey;

import org.apache.shiro.session.Session;
import org.apache.shiro.session.mgt.eis.AbstractSessionDAO;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.Serializable;
import java.util.Collection;
import java.util.List;
import java.util.Set;

/**
 * RedisSessionDAO for shiro 分布式 session
 * @author Rlax
 *
 */
public class RedisSessionDAO extends AbstractSessionDAO {
	
	private final static Logger logger = LoggerFactory.getLogger(RedisSessionDAO.class);
	
    /** 默认1200秒 */
    private int expire = 1200;

    public int getExpire() {
        return expire;
    }

    public void setExpire(int expire) {
        this.expire = expire;
    }

    /**
     * 如DefaultSessionManager在创建完session后会调用该方法；
     * 如保存到关系数据库/文件系统/NoSQL数据库；即可以实现会话的持久化；
     * 主要此处返回的ID.equals(session.getId())；
     *
     * @param session session
     * @return 返回会话ID
     */
    protected Serializable doCreate(Session session) {
        Serializable sessionId = this.generateSessionId(session);
        this.assignSessionId(session, sessionId);
        this.saveSession(session);
        return sessionId;
    }

    /**
     * 根据会话ID获取会话
     *
     * @param serializable 会话ID
     * @return Session
     */
    protected Session doReadSession(Serializable serializable) {
        if (null == serializable) {
            logger.error("session id is null");
            return null;
        }
        return Redis.use().get(CacheKey.CACHE_SHIRO_SESSION + "_" + serializable);
    }

    /**
     * 更新会话
     * 如更新会话最后访问时间/停止会话/设置超时时间/设置移除属性等会调用
     * 更新username --》 sessionID 关系 （不需要会话管理可删除 updSessionRelation）
     *
     * @param session session
     */
    public void update(Session session) {
        //ShiroSessionKit.updSessionRelation(session);
        saveSession(session);
    }

    /**
     * 删除会话
     * 当会话过期/会话停止（如用户退出时）会调用
     *
     * @param session session
     */
    public void delete(Session session) {
        if (null == session || null == session.getId()) {
            logger.error("session or session id is null");
        } else {
            Redis.use().del(CacheKey.CACHE_SHIRO_SESSION + "_" + session.getId());
            logger.debug("delete success shiro key " + session.getId());
        }
    }

    /**
     * 获取当前所有活跃用户，如果用户量多此方法影响性能
     *
     * @return Collection
     */
    public Collection<Session> getActiveSessions() {
        Set<String> keys = Redis.use().keys(CacheKey.CACHE_SHIRO_SESSION + "_*");
        if (keys != null && keys.size() > 0) {
            @SuppressWarnings("unchecked")
			List<Session> sessionList = Redis.use().mget(keys);
            return sessionList;
        }
        return null;
    }

    /**
     * 保存 session
     *
     * @param session Session
     */
    private void saveSession(Session session) {
        if (session == null || session.getId() == null) {
            logger.error("session or session id is null");
            return;
        }
        String key = CacheKey.CACHE_SHIRO_SESSION + "_" + session.getId();
        Redis.use().setex(key, this.expire, session);
    }
}
